/**
 * 检查 value 是否为 Object 的language type。
 * (例如： arrays, functions, objects, regexes,new Number(0), 以及 new String(''))
 * @category Lang
 * @param value 要检查的值。
 * @returns 如果 value 为一个对象，那么返回 true，否则返回 false。
 * @example
 * isObject({})=>true;
 * isObject(null)=>false;
 * isObject(Function)=>true;
 */
export function isObject(value: any) {
  return (
    value != null && (typeof value === "object" || typeof value === "function")
  );
}

/**
 * 检查 value 是否是 类对象。
 * 如果一个值是类对象，那么它不应该是 null，而且 typeof 后的结果是 "object"。
 *  @category Lang
 * @param value 要检查的值。
 * @returns  如果 value 为一个类对象，那么返回 true，否则返回 false。
 */
export function isObjectLike(value: any) {
  return value !== null && typeof value === "object";
}

export function isNumber(value: any) {
  return (
    typeof value === "number" ||
    (isObjectLike(value) && getTag(value) === "[object Number]")
  );
}

export function isString(value: any) {
  return (
    typeof value === "string" ||
    (typeof value === "object" &&
      value != null &&
      !Array.isArray(value) &&
      getTag(value) === "[object String]")
  );
}

export function isBoolean(value: any) {
  return (
    value === true ||
    value === false ||
    (isObjectLike(value) && getTag(value) === "[object Boolean]")
  );
}

export function isRegExp(value: any) {
  return (
    value instanceof RegExp ||
    (typeof value === "object" && getTag(value) === "[object RegExp]")
  );
}

export function isDate(value: any) {
  return (
    value instanceof Date ||
    (typeof value === "object" && getTag(value) === "[object Date]")
  );
}

export function isInteger(value: number) {
  return typeof value == "number" && Math.floor(value) === value;
}

function getTag(value: any): string {
  if (value == null) {
    return value === undefined ? "[object Undefined]" : "[object Null]";
  }
  return Object.prototype.toString.call(value);
}
